package org.jeecg.modules.generator.utils;

import org.apache.shiro.SecurityUtils;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.FileUtil;
import org.jeecg.modules.constant.GenerateConstants;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.modules.generator.entity.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.*;
import java.sql.*;
import java.util.Date;
import java.util.*;
import java.util.regex.Matcher;

/**
 * 描述：代码生成器
 * Created by Ay on 2017/5/1.
 */
@Slf4j
@Component
public class CodeGenerateUtils {

    @Value("${jeecg.path.upload}")
    private String uploadPath;



    /**
     * 获得数据库表连接
     * @return
     * @throws Exception
     */
    public Connection getConnection(SysGenerateDatabaseConfig sysGenerateDatabaseConfig) throws Exception{
        log.info("=====================获取数据库连接===============================");
        Properties props =new Properties();
        Class.forName(sysGenerateDatabaseConfig.getDriverClass());
        props.setProperty("user", sysGenerateDatabaseConfig.getUsername());
        props.setProperty("password", sysGenerateDatabaseConfig.getPassword());
        props.setProperty("remarks", "true");
        Connection connection= DriverManager.getConnection(sysGenerateDatabaseConfig.getUrl(), props);
        return connection;
    }


    /**
     * 获得用户所有表信息集合
     * @return
     * @throws Exception
     */
    public Map<String,Object> isTableExists(String tableName, SysGenerateDatabaseConfig sysGenerateDatabaseConfig)  throws Exception{

        Map<String,Object> map = new HashMap<>();
        Connection connection = getConnection(sysGenerateDatabaseConfig);
        DatabaseMetaData databaseMetaData = connection.getMetaData();
        ResultSet tableRS  = databaseMetaData.getTables("%",sysGenerateDatabaseConfig.getUsername().toUpperCase(),tableName,new String[]{"TABLE"});
        if(tableRS.next()){
            SysGenerateTab tableClass =  new SysGenerateTab();
            ResultSet primaryKeyRS = databaseMetaData.getPrimaryKeys(null,sysGenerateDatabaseConfig.getUsername().toUpperCase().toUpperCase(),tableName);
            while(primaryKeyRS.next()){
                String primaryKeyColumn =  primaryKeyRS.getString("COLUMN_NAME");
                tableClass.setPrimaryName(primaryKeyColumn);    //主键名称
                tableClass.setPrimaryField(org.jeecg.common.util.StringUtils.replaceUnderLineAndUpperCase(primaryKeyColumn,false)); //主键对应实体类属性名称
            }
            tableClass.setTableDescripe(tableRS.getString("REMARKS"));  //表描述
            tableClass.setTableName(tableName);                                      //表名称
            tableClass.setEntityName(org.jeecg.common.util.StringUtils.replaceUnderLineAndUpperCase(tableName,true));  //表对应实体类名称
            map.put("exist",true);
            map.put("table",tableClass);
        }else {
            map.put("exist",false);
        }
        connection.close();
        return map;
    }

    /**
     * 根据表名获取表的列信息
     * @param tableName
     * @return
     */
    public  List<SysGenerateTabColumn>  getColumnListByTableName(String tableName, String primaryKeyColumn, SysGenerateDatabaseConfig sysGenerateDatabaseConfig) throws Exception{

        log.info("=====================获取数据库指定表的字段===============================");
        Connection connection = getConnection(sysGenerateDatabaseConfig);
        DatabaseMetaData databaseMetaData = connection.getMetaData();
        ResultSet resultSet = databaseMetaData.getColumns(null,sysGenerateDatabaseConfig.getUsername().toUpperCase(), tableName,"%");

        List<SysGenerateTabColumn> sysGenerateTabColumnList = new ArrayList<>();
        while(resultSet.next()){
            SysGenerateTabColumn sysGenerateTabColumn = new SysGenerateTabColumn();
            String columnName = resultSet.getString("COLUMN_NAME");
            /*if("CREATE_TIME".equals(columnName) || "CREATE_USER_NAME".equals(columnName) ||
                    "UPDATE_TIME".equals(columnName) || "UPDATE_USER_NAME".equals(columnName)){
                continue;
            }*/
            if(columnName.equals(primaryKeyColumn)){
                sysGenerateTabColumn.setIsPrimaryKey("1");      //字段为主键
            }else{
                sysGenerateTabColumn.setIsPrimaryKey("0");      //字段为主键
            }
            sysGenerateTabColumn.setTableName(tableName);
            //获取字段名称并转换 sys_name变成SysName
            sysGenerateTabColumn.setFieldName(org.jeecg.common.util.StringUtils.replaceUnderLineAndUpperCase(columnName,false));
            //获得列的长度
            Integer columnSize = Integer.valueOf(resultSet.getString("COLUMN_SIZE"));
            //获取数值类型小数点的位数，没有小数点，则为null
            String digits = resultSet.getString("DECIMAL_DIGITS");
            //获取字段类型
            if("NUMBER".equals(resultSet.getString("TYPE_NAME"))){
                if(digits !=null && Integer.valueOf(digits) != 0){
                    Integer size = columnSize - Integer.valueOf(digits);
                    if(size>39){
                        sysGenerateTabColumn.setColumnType("java.lang.Double");
                    }else{
                        sysGenerateTabColumn.setColumnType("java.lang.Float");
                    }
                    sysGenerateTabColumn.setColumSize(columnSize.longValue());
                    sysGenerateTabColumn.setDigits(Integer.valueOf(digits));
                }else{
                    if(columnSize>18){
                        sysGenerateTabColumn.setColumnType("java.math.BigDecimal");
                    }else if(columnSize>10 && columnSize<=18){
                        sysGenerateTabColumn.setColumnType("java.lang.Long");
                    }else if(columnSize>5 && columnSize<=9){
                        sysGenerateTabColumn.setColumnType("java.lang.Integer");
                    }else{
                        sysGenerateTabColumn.setColumnType("java.lang.Short");
                    }
                    sysGenerateTabColumn.setColumSize(columnSize.longValue());
                }
            }else{
                sysGenerateTabColumn.setColumnType(GenerateConstants.typeMap.get(Integer.valueOf(resultSet.getString("DATA_TYPE"))));
                //设置字段的长度
                sysGenerateTabColumn.setColumSize(columnSize.longValue());
            }
            //设置字段是否可以为空
            sysGenerateTabColumn.setRequired(resultSet.getString("IS_NULLABLE").equals("YES")?"false":"true");
            sysGenerateTabColumn.setColumnName(columnName);
            //字段在数据库的注释
            String remarks = resultSet.getString("REMARKS");
            if(StringUtils.isNotEmpty(remarks)){
                sysGenerateTabColumn.setColumnComment(remarks);
            }else{
                sysGenerateTabColumn.setColumnComment(columnName);
            }
            sysGenerateTabColumnList.add(sysGenerateTabColumn);
        }
        connection.close();
        return sysGenerateTabColumnList;
    }
    /**
     * 生成代码
     * @param table
     * @throws Exception
     */
    public String generate(SysGenerateModuleConfig sysGenerateModuleConfig, List<SysGenerateTemplate> sysGenerateTemplateList, SysGenerateTab table) throws Exception{

        log.info("=====================生成业务代码开始===============================");
        String zipPath = "";
        try {
            String saveRootPath = uploadPath+File.separator+ DateUtils.formatDate(new Date(),"yyyyMMdd")+File.separator+table.getTableName();
            File saveRootPathDir = new File(saveRootPath);
            if(!saveRootPathDir.exists()){
                saveRootPathDir.mkdirs();
            }else {
                FileUtil.deleteSubDir(saveRootPath);
            }
            LoginUser loginUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();
            table.setCreateTime(DateUtils.getDate());       //创建时间
            table.setAuthor(loginUser.getUsername());          //作者
            for(SysGenerateTemplate sysGenerateTemplate : sysGenerateTemplateList) {
                generateFile(saveRootPath,sysGenerateModuleConfig,sysGenerateTemplate,table);
            }
            String zipName = "生成代码.ZIP";
            FileUtil.createLocalZipFile(zipName,saveRootPath);
            zipPath = saveRootPath + File.separator + zipName;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }finally{

        }
        log.info("=====================生成业务代码结束===============================");
        return zipPath;

    }

    public static void main(String[] args) {
        FileUtil.createLocalZipFile("demo.zip","D:\\mygenerator\\20210715\\T_ACCUITY_LIST");

    }

    /**
     * 根据模板生成文件
     * @param sysGenerateModuleConfig
     * @param sysGenerateTemplate
     * @param table
     * @throws Exception
     */
    private void generateFile(String saveRootPath, SysGenerateModuleConfig sysGenerateModuleConfig, SysGenerateTemplate sysGenerateTemplate, SysGenerateTab table) throws Exception{

        log.info("=====================生成业务实体类===============================");
        final String suffix = "."+sysGenerateTemplate.getFileType();
        String entityDirPath = null;
        if("java".equals(sysGenerateTemplate.getFileType()) || "xml".equals(sysGenerateTemplate.getFileType())){
            entityDirPath = saveRootPath+File.separator+"manager"+File.separator+sysGenerateModuleConfig.getJavaPath().replaceAll("\\.", Matcher.quoteReplacement(File.separator))+ File.separator+ table.getBussiPath()+File.separator+sysGenerateTemplate.getOutPutPath();
        }else {
            entityDirPath = saveRootPath+File.separator+"views"+ File.separator+ table.getBussiPath()+File.separator+sysGenerateTemplate.getOutPutPath();
        }
        String  suffixFileName = StringUtils.isNotEmpty(sysGenerateTemplate.getSuffixFileName())?sysGenerateTemplate.getSuffixFileName():"";
        String  fileNamePrefix = table.getEntityName()+suffixFileName;
        String  filePath = entityDirPath+ File.separator +table.getEntityName()+suffixFileName + suffix;
        File entityDir = new File(entityDirPath);
        if(!entityDir.exists()){
            entityDir.mkdirs();
        }
        Map<String,Object> dataMap = new HashMap<>();
        dataMap.put("generateEntity",table);
        dataMap.put("rootPackage",sysGenerateModuleConfig.getJavaPath());
        dataMap.put("bussiPackage", table.getBussiPath());
        dataMap.put("fileNamePrefix",fileNamePrefix);
        generateFileByTemplate(sysGenerateTemplate.getTemplateContent(),new File(filePath),dataMap);
    }
    /**
     * 根据模版生成文件
     * @param templateContent
     * @param file
     * @param dataMap
     * @throws Exception
     */
    private void generateFileByTemplate(final String templateContent,File file,Map<String,Object> dataMap) throws Exception{
        String content = FreeMarkerTemplateUtils.freemarkerProcess(dataMap,templateContent);
        FileOutputStream fos = new FileOutputStream(file);
        Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"),10240);
        out.write(content);
        out.flush();
        out.close();
    }


}
